package jcu.salt.io;

import java.beans.XMLDecoder;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.util.zip.GZIPInputStream;

import jcu.sal.common.Response;

/**
 *  TransmissionInputStream
 *  
 *  This stream enables the convenient extraction of a Transmittable instance
 *  of the defined source stream.
 *  
 *  @see Transmittable
 *
 */
public class TransmissionInputStream extends DataInputStream {
	
	private boolean encoded;

	/**
	 * Initializes the stream with the given input stream as source
	 * and using encoded transmission as default
	 * @param in source stream
	 */
	public TransmissionInputStream(InputStream in) {
		this(in, false);
	}
	
	/**
	 * Initializes the stream with the given input stream as source.
	 * @param in source stream
	 * @param encoded if true, encode in xml and gzip
	 */
	public TransmissionInputStream(InputStream in, boolean encoded) {
		super(in);
		this.encoded = encoded;
	}
	
	/**
	 * Tries to extract a instance of the class {@link Transmittable} from
	 * the input stream. An exception will be thrown if it is not 
	 * possible to extract such an object from the source stream.
	 * @return extracted Transmittable object
	 * @throws IOException
	 */
	public Transmittable readTransmitable() throws IOException {
	    Object received = readObject();
	    
		if(received != null && received instanceof Transmittable) {
			return (Transmittable)received;
		}
		
		throw new IOException("can not read Transmittable");		
	}
	
	/**
	 * Tries to extract a instance of the class {@link Response} from
	 * the input stream. An exception will be thrown if it is not 
	 * possible to extract such an object from the source stream.
	 * @return extracted Response object
	 * @throws IOException
	 */
	public Response readResponse() throws IOException {
	    Object received = readObject();
	    
		if(received != null && received instanceof Response) {
			return (Response)received;
		}
		
		throw new IOException("can not read Response");		
	}

	/**
	 * Reads an object from the input stream.
	 * @return object received of null
	 * @throws IOException
	 */
	private Object readObject() throws IOException {
		Object received = null;
		
		BufferedInputStream bufin = new BufferedInputStream(in);
		
		if(encoded) {
		    GZIPInputStream gzipin = new GZIPInputStream(bufin);
		    XMLDecoder xmldec = new XMLDecoder(gzipin);
		    received = xmldec.readObject();
		    xmldec.close();		
		} else {
			ObjectInputStream in = new ObjectInputStream(bufin);
			try {
				received = in.readObject();
			} catch (ClassNotFoundException e) {				
				e.printStackTrace();
			}
			in.close();
		}
		return received;
	}

}
